"""
a1:  区间值模糊数 格式为([],[])

self.q: q值
self.x: 一个参数时所用的变量,在dombi中，x >= 1

a2:     区间值模糊数 格式为([],[])

编写时间:2022/6/30 8:47
编写人:操祉豪
参考文献:Some Dombi aggregation of Q‐rung orthopair
fuzzy numbers in multiple‐attribute decision
making
"""
from Utilities.AutoGetOperator.selectPackage import get_func

Operator_IVQ_ROFS=get_func(r'Operators/OperationOperators/OperatorIVQROF.py','Operator_IVQ_ROFS')

class Dombi(Operator_IVQ_ROFS):

    def add(self, a1, a2, q=0, x=0, *waste1, **waste2):
        '''
        Dombi的加法运算
        :param a1:
        :param a2:
        :param q:
        :param x: x必须大于等于1
        :param waste1:
        :param waste2:
        :return: 区间值([],[])
        '''
        u1 = a1[0]
        u2 = a2[0]
        v1 = a1[1]
        v2 = a2[1]

        if x < 1:
            x = self.x
        if q <= 0:
            q = self.q

        u = [
            (1 - (1 / (1 + ((u1[0] ** q / (1 - u1[0] ** q)) ** x + (u2[0] ** q / (1 - u2[0] ** q)) ** x) ** (1 / x)))) ** (1 / q),
            (1 - (1 / (1 + ((u1[1] ** q / (1 - u1[1] ** q)) ** x + (u2[1] ** q / (1 - u2[1] ** q)) ** x) ** (1 / x)))) ** (1 / q)
        ]

        v = [
            (1 - (1 / (1 + (((1 - v1[0] ** q) / v1[0] ** q) ** x + ((1 - v2[0] ** q) / v2[0] ** q) ** x) ** (
                        1 / x)))) ** (1 / q),
            (1 - (1 / (1 + (((1 - v1[1] ** q) / v1[1] ** q) ** x + ((1 - v2[1] ** q) / v2[1] ** q) ** x) ** (
                    1 / x)))) ** (1 / q)
        ]

        return (u, v)

    def multi(self, a1, a2, q=0, x=0, *waste1, **waste2):
        '''
        Dombi的乘法运算
        :param a1:
        :param a2:
        :param q:
        :param x:
        :param waste1:
        :param waste2:
        :return: 区间值([],[])
        '''
        u1 = a1[0]
        u2 = a2[0]
        v1 = a1[1]
        v2 = a2[1]

        if x < 1:
            x = self.x
        if q <= 0:
            q = self.q

        u = [
            (1 - (1 / (1 + (((1 - u1[0] ** q) / u1[0] ** q) ** x + ((1 - u1[0] ** q) / u1[0] ** q) ** x) ** (
                    1 / x)))) ** (1 / q),
            (1 - (1 / (1 + (((1 - u1[1] ** q) / u1[1] ** q) ** x + ((1 - u2[1] ** q) / u2[1] ** q) ** x) ** (
                    1 / x)))) ** (1 / q)
        ]

        v = [
            (1 - (1 / (1 + ((v1[0] ** q / (1 - v1[0] ** q)) ** x + (v2[0] ** q / (1 - v2[0] ** q)) ** x) ** (
                        1 / x)))) ** (1 / q),
            (1 - (1 / (1 + ((v1[1] ** q / (1 - v1[1] ** q)) ** x + (v2[1] ** q / (1 - v2[1] ** q)) ** x) ** (
                        1 / x)))) ** (1 / q)
        ]

        return (u, v)

    def kmulti(self, a, k, q=0, x=0, *waste1, **waste2):
        '''
        Dombi的数乘运算
        :param a:
        :param k:
        :param q:
        :param x:
        :param waste1:
        :param waste2:
        :return: 区间值([],[])
        '''
        u1 = a[0]
        v1 = a[1]

        if x < 1:
            x = self.x
        if q <= 0:
            q = self.q

        u = [
            (1 - (1 / (1 + (k * (u1[0] ** q / (1 - u1[0] ** q)) ** x) ** (1 / x)))) ** (1 / q),
            (1 - (1 / (1 + (k * (u1[1] ** q / (1 - u1[1] ** q)) ** x) ** (1 / x)))) ** (1 / q)
        ]

        v = [
            (1 - (1 / (1 + (k * ((1 - v1[0] ** q) / v1[0] ** q) ** x) ** (1 / x)))) ** (1 / q),
            (1 - (1 / (1 + (k * ((1 - v1[1] ** q) / v1[1] ** q) ** x) ** (1 / x)))) ** (1 / q),
        ]

        return (u, v)

    def pow(self, a, k, q=0, x=0, *waste1, **waste2):
        '''
        Dombi的数乘运算
        :param a:
        :param k:
        :param q:
        :param x:
        :param waste1:
        :param waste2:
        :return: 区间值([],[])
        '''
        u1 = a[0]
        v1 = a[1]

        if x < 1:
            x = self.x
        if q <= 0:
            q = self.q

        u = [
            (1 - (1 / (1 + (k * ((1 - u1[0] ** q) / u1[0] ** q) ** x) ** (1 / x)))) ** (1 / q),
            (1 - (1 / (1 + (k * ((1 - u1[1] ** q) / u1[1] ** q) ** x) ** (1 / x)))) ** (1 / q),
        ]

        v = [
            (1 - (1 / (1 + (k * (v1[0] ** q / (1 - v1[0] ** q)) ** x) ** (1 / x)))) ** (1 / q),
            (1 - (1 / (1 + (k * (v1[1] ** q / (1 - v1[1] ** q)) ** x) ** (1 / x)))) ** (1 / q)
        ]

        return (u, v)


class DombiA(Dombi):

    def getResult(self):
        '''
        function：基础的算数平均公式
        :return: AA公式计算的结果
        '''
        result=self.data_list[0]
        for i in range(1,len(self.data_list)):
            result=self.add(result,self.data_list[i])
        result=self.kmulti(result,1/len(self.data_list))

        return result

class DombiGA(Dombi):

    def getResult(self):
        data_list = self.data_list
        res = data_list[0]
        n = len(data_list)
        for idx in range(n):
            if idx == 0:
                continue
            res = self.multi(res, data_list[idx])
        res = self.pow(res, 1 / n)

        return res

class DombiWA(Dombi):

    def getResult(self):
        data_list = self.data_list
        weight_list = self.weight_list
        q = self.q
        res = self.kmulti(data_list[0], weight_list[0])
        n = len(weight_list)
        for idx in range(n):
            if idx == 0:
                continue
            res = self.add(res, self.kmulti(data_list[idx], weight_list[idx], q))
        return res

class DombiWGA(Dombi):

    def getResult(self):
        data_list = self.data_list
        weight_list = self.weight_list
        q = self.q
        n = len(data_list)
        res = self.pow(data_list[0], weight_list[0])
        for idx in range(n):
            if idx == 0:
                continue
            res = self.multi(res, self.pow(data_list[idx], weight_list[idx], q))
        return res

class DombiOWA(Dombi):

    def getResult(self):
        data_list = self.sortdata()
        weight_list = self.weight_list
        q = self.q
        n = len(data_list)
        res = self.kmulti(data_list[0], weight_list[0])
        for idx in range(n):
            if idx == 0:
                continue
            res = self.add(res, self.kmulti(data_list[idx], weight_list[idx], q))
        return res

if __name__ == '__main__':
    data_list = [([0.31, 0.24], [0.73, 0.72]), ([0.97, 0.12], [0.12, 0.05]),
                 ([0.8, 0.52], [0.73, 0.15]), ([0.91, 0.49], [0.42, 0.47]), ([0.95, 0.06], [0.19, 0.1])]
    weight_list = [0.1, 0.2, 0.3, 0.1, 0.3],
    # Pa = A(data_list)
    Pa = DombiGA(data_list)
    # Pa = WA(data_list,weight_list)
    # Pa = WGA(data_list,weight_list)
    # Pa = OWA(data_list,weight_list)
    print(Pa.getResult())
